import java.util.*;
import java.awt.*;
import java.io.*;

/**
* Contains the local information about a piece (not it's position on
* the game board for example).
*/
public class Piece implements Serializable
{
	private Point point;
	private int pseudoPlacement = 0;
	public int pseudoSkip = 0;
	/**
	* The owner of this piece
	*/
	private Player owner;
	/**
	* The type of the piece, used to retrieve the correct matrix of
	* Bricks.
	*/
	private int pieceType;
	/**
	* Defines exactly how the piece is built up with bricks. An unoccupied
	* slot is defined by null.
	*/
	private Brick[][] matrix;
	/**
	* Defines the rotation of the piece. Used to retrieve the correct
	* matrix of Bricks.
	*/
	private int rotationState;

	/**
	* Creates a new piece with a given owner, type and rotation. The Brick
	* matrix will be retrieved based on this.
	*
	* @param owner the player owner of this piece
	* @param pieceType the type of the brick to be constructed
	* @param rotationState the starting rotation of this piece
	*/
	public Piece(Player owner, int pieceType, int rotationState) {
		this.owner = owner;
		this.rotationState = rotationState;
		this.pieceType = pieceType;
		this.point = new Point();

		int[][] edges = Multitris.pieceStates.get(pieceType).get(rotationState);

		matrix = new Brick[edges.length][edges[0].length];
		for (int x=0; x<edges.length; x++) {
			for (int y=0; y<edges[x].length; y++) {
				if (edges[x][y] == -1) {
					matrix[x][y] = null;
				} else {
					matrix[x][y] = new Brick(owner, edges[x][y]);
				}
			}
		}
	}

	/**
	* Returns the owner for this piece.
	*
	* @return the owner
	*/
	public Player getPlayer() {
		return owner;
	}


	/**
	* Returns the Brick matrix for this piece.
	*
	* @return the Brick matrix
	*/
	public Brick[][] getBricks() {
		return matrix;
	}

	public void setPseudoPlacement(int placement) {
		pseudoPlacement = placement;
	}

	public int getPseudoPlacement() {
		return pseudoPlacement;
	}

	
	public int getMaxY() {
		for (int y=3; y>=0; y--) {
			for (int x=0; x<4; x++) {
				if (matrix[x][y] != null) {
					return y;
				}
			}
		}
		return 0;
	}
	
	public int getMinY() {
		for (int y=0; y<4; y++) {
			for (int x=0; x<4; x++) {
				if (matrix[x][y] != null) {
					return y;
				}
			}
		}
		return 0;
	}
	
	public int getMaxX() {
		for (int x=3; x>=0; x--) {
			for (int y=0; y<4; y++) {
				if (matrix[x][y] != null) {
					return x;
				}
			}
		}
		return 0;
	}
	
	public int getMinX() {
		for (int x=0; x<4; x++) {
			for (int y=0; y<4; y++) {
				if (matrix[x][y] != null) {
					return x;
				}
			}
		}
		return 0;
	}

	public int getRotation() {
		return rotationState;
	}

	public int getRotationStatesCount() {
		return Multitris.pieceStates.get(pieceType).size();
	}


	/**
	* Reconstructs the piece but with another rotation.
	*
	* @param clockwise the number of clockwise rotation steps to rotate with. Negative numbers will rotate the piece counter-clockwise.
	* @return true
	*/
	public boolean rotate(int clockwise) {

		ArrayList<int[][]> rotations = Multitris.pieceStates.get(pieceType);
		rotationState = (rotationState + clockwise) % rotations.size();
		if (rotationState < 0) {
			rotationState += rotations.size();
		}

		int[][] newEdges = rotations.get(rotationState);
		for (int x=0; x<newEdges.length; x++) {
			for (int y=0; y<newEdges[x].length; y++) {
				if (newEdges[x][y] == -1) {
					matrix[x][y] = null;
				} else {
					matrix[x][y] = new Brick(owner, newEdges[x][y]);
				}
			}
		}

		return true;
	}

	public void setPoint(Point point)
	{
		this.point = point;

	}

	public Point getPoint()
	{
		return point;
	}
}